'''
# 利用PET图像自动提取肺部边界
# 取肺中心点为原点，肺部外接矩形作为长宽系数，计算相对坐标
# 排除左右肺对应位置坐标的差异
# 排除不同人肺尺寸大小的差异
'''

import csv
import cv2
import pandas
import pydicom
import numpy as np

def IOU(box1, box2):
    '''

    :param box1: [x1, y1, x2, y2] 左上角的坐标和右下角的坐标
    :param box2: [x1, y1, x2, y2]
    :return: iou_ratio--交并比
    '''

    width1 = abs(box1[2]-box1[0])
    height1 = abs(box1[1]-box1[3])
    width2 = abs(box1[2]-box2[0])
    height2 = abs(box2[1]-box2[3])

    x_max = max(box1[0], box1[2], box2[0], box2[2])
    y_max = max(box1[1], box1[3], box2[1], box2[3])
    x_min = min(box1[0], box1[2], box2[0], box2[2])
    y_min = min(box1[1], box1[3], box2[1], box2[3])

    iou_width = width1+width2-x_max+x_min
    iou_height = height1+height2-y_max+y_min

    if iou_width<=0 or iou_height<=0:
        iou_ratio = 0
    else:
        iou_area = iou_height*iou_width
        box1_area = width1*height1
        box2_area = width2*height2
        iou_ratio = iou_area/(box1_area+box2_area-iou_area)
    return iou_ratio


def read_info():
    data_path = 'D:/lung_cancer/data/all_data4.csv'
    data = []
    f = csv.reader(open(data_path, 'r'))
    for i in f:
        data.append(i)
    new_data = []

    for line in data[1:]:
        patient = str(line[1])
        # cancer_type = str(line[6])
        pet_path = str(line[32])
        read_pet(patient, pet_path)
        # if new_x == 0:
        #     print('%s is ERROR'% (patient))
        # else:
        #     line.append(new_x)
        #     line.append(new_y)
        #     new_data.append(line)
    # data[0].append('median_x')
    # data[0].append('median_y')
    # df = pandas.DataFrame(new_data, columns=data[0])
    # df.to_csv('D:/lung_cancer/data/all_data5.csv', index=False)


def read_pet(patient, pet_path):
    # pet_path = 'D:/lung_cancer/data/origin_data/3107/PET/PT112_1.2.840.113619.2.131.9999.1209881422.754573.dcm'
    slice = pydicom.read_file('H:/'+pet_path)
    pet_array = slice.pixel_array
    # slope = slice.RescaleIntercept
    # intercept = slice.RescaleIntercept
    # pet_array = pet_array.astype(np.int32)
    # if slope != 1:
    #     pet_array = slope * pet_array.astype(np.float64)
    #     pet_array = pet_array.astype(np.int32)
    # pet_array += np.int32(intercept)
    # print(pet_array.shape)
    pet_array = pet_array/np.float(np.max(pet_array))
    binary = (pet_array > 0.05).astype(float)
    binary = np.asarray(binary * 255, dtype=np.uint8)
    img = cv2.bitwise_not(binary)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
    erosion = cv2.erode(img, kernel, iterations=1)
    result = cv2.bitwise_not(erosion)
    # cv2.imshow('pet_array', pet_array)
    # cv2.imshow('binary', binary)
    # cv2.imshow('erosion', erosion)
    # cv2.imshow('result', result)
    # cv2.waitKey()
    # cv2.destroyAllWindows()

    image, contours, hierarchy = cv2.findContours(result, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    xmin = 128
    ymin = 128
    xmax = 0
    ymax = 0
    for c in contours:
        x, y, w, h = cv2.boundingRect(c)
        if x < xmin:
            xmin = x
        if y < ymin:
            ymin = y
        if x+w > xmax:
            xmax = x+w
        if y+h > ymax:
            ymax = y+h

    cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 1)
    cv2.imshow('draw', img)
    keyword = cv2.waitKey()
    if keyword == ord('d') or keyword == ord('D'):
        print('%s xmin:%d-->ymin:%d-->xmax:%d-->ymax:%d'%(patient, xmin, ymin, xmax, ymax))
    else:
        print('%s ERROR' % (patient))
    cv2.destroyAllWindows()


# 将CT病灶坐标和半径转换到pet原图上
def ctcoord_to_petcoord():
    data_path = 'D:/lung_cancer/data/all_data3.csv'
    f = csv.reader(open(data_path, 'r'))
    data = []
    for i in f:
        data.append(i)

    new_data = []

    for line in data[1:]:
        patient = str(line[1])
        ct_size = int(line[7])
        pet_size = int(line[8])
        ct_spacing = float(line[9])
        pet_spacing = float(line[12])
        real_size = int(round(pet_size * pet_spacing / ct_spacing))
        border = (real_size - ct_size) // 2

        x = int(line[3])
        y = int(line[4])
        r = int(line[5])

        newX = x+border
        newY = y+border

        petX = int(newX/real_size*pet_size)
        petY = int(newY/real_size*pet_size)
        petR = int(r*ct_spacing/pet_spacing)

        line.append(petX)
        line.append(petY)
        line.append(petR)
        new_data.append(line)
    data[0].append('petX')
    data[0].append('petY')
    data[0].append('petR')
    df = pandas.DataFrame(new_data, columns=data[0])
    df.to_csv('D:/lung_cancer/data/all_data3.csv', index=False)


# 以上几个函数的整合，计算病人肺部区域的中心原点和肺部长宽
def get_center_coord():
    data_path = 'D:/lung_cancer/data/all_data4.csv'
    data = []
    f = csv.reader(open(data_path, 'r'))
    for i in f:
        data.append(i)
    new_data = []
    data[0].append('center_x')
    data[0].append('center_y')
    data[0].append('lungW')
    data[0].append('lungH')
    for line in data[1:]:
        patient = str(line[1])
        pet_path = str(line[32])

        slice = pydicom.read_file('H:/' + pet_path)
        pet_array = slice.pixel_array
        pet_array = pet_array / np.float(np.max(pet_array))
        show_array = np.asarray((1-pet_array)*350, dtype=np.uint8)

        cv2.imshow('show', show_array)
        cv2.waitKey()
        cv2.destroyAllWindows()

        binary = (pet_array > 0.05).astype(float)
        binary = np.asarray(binary * 255, dtype=np.uint8)
        img = cv2.bitwise_not(binary)
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
        erosion = cv2.erode(img, kernel, iterations=1)
        result = cv2.bitwise_not(erosion)

        image, contours, hierarchy = cv2.findContours(result, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        xmin = 200
        ymin = 200
        xmax = 0
        ymax = 0
        for c in contours:
            x, y, w, h = cv2.boundingRect(c)
            if x < xmin:
                xmin = x
            if y < ymin:
                ymin = y
            if x + w > xmax:
                xmax = x + w
            if y + h > ymax:
                ymax = y + h

        cv2.rectangle(show_array, (xmin, ymin), (xmax, ymax), (0, 255, 0), 1)
        cv2.imshow('draw', show_array)
        keyword = cv2.waitKey()
        if keyword == ord('d') or keyword == ord('D'):
            line.append((xmin+xmax)//2)
            line.append((ymin+ymax)//2)
            line.append(xmax-xmin)
            line.append(ymax-ymin)

            # print('%s xmin:%d-->ymin:%d-->xmax:%d-->ymax:%d' % (patient, xmin, ymin, xmax, ymax))
        else:
            line.append(0)
            line.append(0)
            line.append(0)
            line.append(0)
            print('%s ERROR' % (patient))

        new_data.append(line)
        cv2.destroyAllWindows()

    # df = pandas.DataFrame(new_data, columns=data[0])
    # df.to_csv('D:/lung_cancer/data/all_data5.csv', index=False)


# 得到排除肺部边界长宽影响和PET影像偏移的坐标cx, cy
def get_cx_cy():
    data_path = 'D:/lung_cancer/data/all_data6.csv'
    data = []
    f = csv.reader(open(data_path, 'r'))
    for i in f:
        data.append(i)
    new_data = []
    data[0].append('newx')
    data[0].append('newy')
    data[0].append('cx')
    data[0].append('cy')
    for line in data[1:]:
        patient = str(line[1])
        petx = int(line[36])
        pety = int(line[37])

        center_x = int(line[46])
        center_y = int(line[47])
        lungw = float(line[48])
        lungh = float(line[49])

        newx = petx-center_x
        newy = pety-center_y
        cx = newx/lungw
        cy = newy/lungh

        line.append(newx)
        line.append(newy)
        line.append(cx)
        line.append(cy)


        new_data.append(line)

    # df = pandas.DataFrame(new_data, columns=data[0])
    # df.to_csv('D:/lung_cancer/data/all_data7.csv', index=False)



if __name__ == '__main__':
    # ctcoord_to_petcoord()
    # read_info()
    get_center_coord()
    # get_cx_cy()